package at.fhooe.mcm.logic.sensors;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import at.fhooe.mcm.logic.core.Core;
import at.fhooe.mcm.logic.event.EventManager;
import at.fhooe.mcm.logic.logging.ConsoleLoggingService;
import at.fhooe.mcm.logic.sensors.events.SensorCreatedEvent;
import at.fhooe.mcm.logic.sensors.events.SensorDestroyedEvent;

/**
 * Base class for all game entities.
 */
public abstract class Sensor implements Serializable, Runnable
{
	private static final long	serialVersionUID	= 3136136430395624914L;
	
	protected String			m_id;
	protected String			m_name;
	protected boolean			m_isPublic;
	protected boolean			m_isPull;
	protected boolean			isEngaged;
	protected int				m_updatePeriod;
	
	transient protected Thread	m_thread;
	transient protected Core	m_core;

	public Sensor(Core _core, String _id, String _name, boolean _isPublic, boolean _isPull, int _updatePeriod)
	{
		m_core = _core;
		m_id = _id;
		m_name = _name;
		m_isPublic = _isPublic;
		m_isPull = _isPull;
		m_updatePeriod = _updatePeriod;
		m_thread = new Thread(this);

		ConsoleLoggingService.getInstance(m_core).logInfo(_id, "sensor created");
	}

	public final Core getCore()
	{
		return m_core;
	}

	public final String getID()
	{
		return m_id;
	}

	public final boolean isEngaged()
	{
		return isEngaged;
	}

	public final void engage()
	{
		setUp();
		isEngaged = true;
		EventManager.getInstance(m_core).enqueueEvent(new SensorCreatedEvent(m_id, m_name, getType()));

		ConsoleLoggingService.getInstance(m_core).logInfo(m_id, "sensor engaged");
	}

	public boolean isPushingService()
	{
		return !m_isPull;
	}

	public boolean isPublicService()
	{
		return m_isPublic;
	}

	public final void disengage()
	{
		tearDown();
		isEngaged = false;
		EventManager.getInstance(m_core).enqueueEvent(new SensorDestroyedEvent(m_id));

		ConsoleLoggingService.getInstance(m_core).logInfo(m_id, "sensor disengaged");
	}

	public String getSensorName()
	{
		return m_name;
	}

	public boolean isPublic()
	{
		return m_isPublic;
	}

	public boolean isPull()
	{
		return m_isPull;
	}

	public int getUpdatePeriod()
	{
		return m_updatePeriod;
	}
	
	public void setSensorName(String _name)
	{
		m_name = _name;
	}

	public void setPublic(boolean _isPublic)
	{
		m_isPublic = _isPublic;
	}

	public void setPull(boolean _isPull)
	{
		m_isPull = _isPull;
		
		if(m_isPull) {
			tearDown();
		} else {
			setUp();
		}
	}

	public void setUpdatePeriod(int _updatePeriod)
	{
		m_updatePeriod = _updatePeriod;
	}
	
	private void writeObject(ObjectOutputStream out) throws IOException
	   {
	     out.defaultWriteObject();
	   }
	  
	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
	{
	     // our "pseudo-constructor"
	     in.defaultReadObject();	   
	     
	     // now we are a "live" object again, so let's run rebuild and start
	     m_thread = new Thread(this);
	}

	public void initialize(Core _core)
	{
		m_core = _core;
	}
	
	public abstract String getType();

	protected abstract void setUp();

	protected abstract void tearDown();

	public abstract void update();
}
